home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / comm / misc / zedzap05.lha / zm.c < prev    next >
C/C++ Source or Header  |  1992-11-26  |  19KB  |  765 lines

  1. /**********************************************************************
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    01-19-87  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * 29 July 89:
  7.  * Major overhaul by Rick Huebner for adaptation to Amiga XPR protocol spec
  8.  *
  9.  * 28 October 89:
  10.  * Converted to Lattice C 5.04
  11.  *
  12.  * 15 November 1991
  13.  * Code added to support CRC-32 by William M. Perkins.
  14.  **********************************************************************/
  15.  
  16. #include <proto/all.h>
  17. #include <exec/types.h>
  18. #include <ctype.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include "xproto.h"
  22. #include "zmodem.h"
  23. #include "xprzmodem.h"
  24. #include "zcrc.h"
  25.  
  26. struct ExecBase *SysBase = (struct ExecBase*)4l;
  27.  
  28. static char *frametypes[] =
  29. {
  30.    "Carrier Lost",         /* -3 */
  31.    "TIMEOUT",              /* -2 */
  32.    "ERROR",                /* -1 */
  33. #define FTOFFSET 3
  34.    "ZRQINIT",
  35.    "ZRINIT",
  36.    "ZSINIT",
  37.    "ZACK",
  38.    "ZFILE",
  39.    "ZSKIP",
  40.    "ZNAK",
  41.    "ZABORT",
  42.    "ZFIN",
  43.    "ZRPOS",
  44.    "ZDATA",
  45.    "ZEOF",
  46.    "ZFERR",
  47.    "ZCRC",
  48.    "ZCHALLENGE",
  49.    "ZCOMPL",
  50.    "ZCAN",
  51.    "ZFREECNT",
  52.    "ZCOMMAND",
  53.    "ZSTDERR",
  54.    "xxxxx"
  55. #define FRTYPES 22      /* Total number of frame types in this array */
  56.                         /*  not including psuedo negative entries */
  57.    };
  58.  
  59. static UBYTE DLE_actions[] =
  60. {
  61.    0,0,0,0,0,0,0,0, 0,0,0,0,0,2,0,0, 1,1,0,1,0,0,0,0, 1,0,0,0,0,0,0,0,
  62.    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  63.    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  64.    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  65.  
  66.    0,0,0,0,0,0,0,0, 0,0,0,0,0,2,0,0, 1,1,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,
  67.    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  68.    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  69.    0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
  70.    };
  71.  
  72. char ProtocolInfo[] = {
  73.    "XprZedZap.Library By Yves Konigshofer\r\n",
  74.    "\r\n"
  75.    "Original ZModem Protocol Primitives: Chuck Forsberg (Omen Technology Inc.)\r\n",
  76.    "   Adaptation To Amiga XPR Protocol: Rick Huebner\r\n",
  77.    "        Addition Of CRC-32 Routines: William M. Perkins\r\n",
  78.    "       Combining Of v2.10 And v2.5x: Yves Konigshofer\r\n",
  79.    "                   ZedZap Additions: Yves Konigshofer\r\n",
  80.    "\r\n",
  81.    "This Library IS Public Domain...\r\n"
  82. };
  83.  
  84. /**********************************************************
  85.  *      void zsbhdr(struct Vars *v, USHORT type)
  86.  *
  87.  * Send ZMODEM binary header hdr of type type
  88.  **********************************************************/
  89. void zsbhdr(struct Vars *v, USHORT type)
  90. {
  91.    UBYTE  *hdr = v->Txhdr;
  92.    short  n;
  93.    USHORT crc;
  94.    ULONG  crc32;
  95.  
  96.    xsendline(v, ZPAD);
  97.    xsendline(v, ZDLE);
  98.  
  99.    if (v->Crc32t = v->Txfcs32)  /* zsbh32() */
  100.    {
  101.       xsendline(v, ZBIN32);
  102.       zsendline(v, (UBYTE) type);
  103.  
  104.       crc32 = 0xFFFFFFFFL;
  105.       crc32 = UPDC32(type, crc32);
  106.  
  107.       for (n = 4; --n >= 0; ++hdr)
  108.       {
  109.          crc32 = UPDC32((0377 & *hdr), crc32);
  110.          zsendline(v, *hdr);
  111.          }
  112.       crc32 = ~crc32;
  113.       for (n = 4; --n >= 0;)
  114.       {
  115.          zsendline(v, (int) crc32);
  116.          crc32 >>= 8;
  117.          }
  118.       }
  119.    else
  120.    {
  121.       xsendline(v, ZBIN);
  122.       zsendline(v, (UBYTE) type);
  123.  
  124.       crc = updcrc(type, 0);
  125.       for (n = 4; --n >= 0; )
  126.       {
  127.          zsendline(v, *hdr);
  128.          crc = updcrc(((USHORT) (*hdr++)), crc);
  129.          }
  130.  
  131.       crc = updcrc(((USHORT) 0), crc);
  132.       crc = updcrc(((USHORT) 0), crc);
  133.       zsendline(v, (UBYTE) (crc >> 8));
  134.       zsendline(v, (UBYTE) crc);
  135.       }
  136.    }    /* End of void zsbhdr() */
  137.  
  138. /**********************************************************
  139.  *      void zshhdr(struct Vars *v, USHORT type)
  140.  *
  141.  * Send ZMODEM HEX header hdr of type type
  142.  **********************************************************/
  143. void zshhdr(struct Vars *v, USHORT type)
  144. {
  145.    UBYTE *hdr = v->Txhdr;
  146.    short n;
  147.    USHORT crc;
  148.  
  149.    sendline(v, ZPAD);
  150.    sendline(v, ZPAD);
  151.    sendline(v, ZDLE);
  152.    sendline(v, ZHEX);
  153.    zputhex(v, (UBYTE) type);
  154.    v->Crc32t = 0;
  155.  
  156.    crc = updcrc(type, 0);
  157.    for (n = 4; --n >= 0; )
  158.    {
  159.       zputhex(v, *hdr);
  160.       crc = updcrc(((USHORT) (*hdr++)), crc);
  161.       }
  162.  
  163.    crc = updcrc(((USHORT) 0), crc);
  164.    crc = updcrc(((USHORT) 0), crc);
  165.    zputhex(v, (UBYTE) (crc >> 8));
  166.    zputhex(v, (UBYTE) crc);
  167.  
  168.    /* Make it printable on remote machine */
  169.    sendline(v, '\r');
  170.    sendline(v, '\n');
  171.    /* Uncork the remote in case a fake XOFF has stopped data flow */
  172.    if (type != ZFIN)
  173.       sendline(v, XON);
  174.    }    /* End of void zshhdr() */
  175.  
  176. /**********************************************************
  177.  *      void zsdata() and void zsda32()
  178.  *
  179.  * Send binary array buf of length length, with ending
  180.  * ZDLE sequence frameend
  181.  **********************************************************/
  182. void zsdata(struct Vars *v, short length, USHORT frameend)
  183. {
  184.    UBYTE  *buf, *outptr, c;
  185.    USHORT crc;
  186.    ULONG  crc32;
  187.  
  188.    buf = v->Pktbuf;
  189.    outptr = v->Outbuf + v->Outbuflen;
  190.    crc32 = 0xFFFFFFFFL;                 /* zsda32() */
  191.    crc = 0;
  192.  
  193.    while (--length >= 0)
  194.    {
  195.       switch (DLE_actions[c = *buf])
  196.       {
  197.       case 2:
  198.          if (v->Lastzsent != '@')
  199.             goto sendit;
  200.          /* Fallthrough */
  201.       case 1:
  202.          *outptr++ = ZDLE;
  203.          c ^= 0x40;
  204. sendit:
  205.       case 0:
  206.          *outptr++ = v->Lastzsent = c;
  207.          }
  208.       if (v->Crc32t)                    /* zsda32() */
  209.          crc32 = UPDC32((0xFF & *buf++), crc32);
  210.       else
  211.          crc = updcrc(((USHORT) (*buf++)), crc);
  212.       }
  213.    *outptr++ = ZDLE;
  214.    *outptr++ = frameend;
  215.    v->Outbuflen = outptr - v->Outbuf;
  216.  
  217.    if (v->Crc32t)                               /* zsda32() */
  218.    {
  219.       crc32 = UPDC32(frameend, crc32);
  220.       crc32 = ~crc32;
  221.       for (length = 4; --length >= 0; )
  222.       {
  223.          zsendline(v, (int) crc32);
  224.          crc32 >>= 8;
  225.          }
  226.       }
  227.    else
  228.    {
  229.       crc = updcrc(frameend, crc);
  230.       crc = updcrc(((USHORT) 0), crc);
  231.       crc = updcrc(((USHORT) 0), crc);
  232.       zsendline(v, (UBYTE) (crc >> 8));
  233.       zsendline(v, (UBYTE) crc);
  234.       }
  235.  
  236.    if (frameend == ZCRCW)
  237.       xsendline(v, XON);
  238.    }    /* End of void zsdata() */
  239.  
  240. /**********************************************************
  241.  *      short zrdata(struct Vars *v, UBYTE *buf, short length)
  242.  *
  243.  * Receive array buf of max length with ending ZDLE sequence
  244.  * and CRC-16.  Returns the ending character or error code.
  245.  **********************************************************/
  246. short zrdata(struct Vars *v, UBYTE *buf, short length)
  247. {
  248.    short c, d;
  249.    USHORT crc;
  250.  
  251.    if (v->Rxframeind == ZBIN32)
  252.       return zrdat32(v, buf, length);
  253.  
  254.    crc = v->Rxcount = 0;
  255.    for (;;)
  256.    {
  257.       if ((c = zdlread(v)) & ~0xFF)
  258.       {
  259. crcfoo:
  260.          switch (c)
  261.          {
  262.          case GOTCRCE:
  263.          case GOTCRCG:
  264.          case GOTCRCQ:
  265.          case GOTCRCW:
  266.             crc = updcrc(((d = c) & 0xFF), crc);
  267.             if ((c = zdlread(v)) & ~0xFF)
  268.                goto crcfoo;
  269.             crc = updcrc(c, crc);
  270.             if ((c = zdlread(v)) & ~0xFF)
  271.                goto crcfoo;
  272.             crc = updcrc(c, crc);
  273.             if (crc & 0xFFFF)
  274.             {
  275.                strcpy(v->Msgbuf, "Bad Data Packet CRC-16 ");
  276.                return ERROR;
  277.                }
  278.             return d;
  279.          case GOTCAN:
  280.             strcpy(v->Msgbuf, "Transfer Cancelled (Remote Sent ZCAN)");
  281.             return ZCAN;
  282.          case TIMEOUT:
  283.             strcpy(v->Msgbuf, "Data Packet Timeout ");
  284.             return c;
  285.          case RCDO:
  286.             strcpy(v->Msgbuf, "Transfer Cancelled (Remote Dropped Carrier)");
  287.             return c;
  288.          default:
  289.             strcpy(v->Msgbuf, "Unrecognizable Data Packet ");
  290.             return c;
  291.             }
  292.          }
  293.       if (--length < 0)
  294.       {
  295.          strcpy(v->Msgbuf, "Data Packet Too Long ");
  296.          return ERROR;
  297.          }
  298.       ++v->Rxcount;
  299.       *buf++ = c;
  300.       crc = updcrc(c, crc);
  301.       continue;
  302.       }
  303.    }    /* End of short zrdata() */
  304.  
  305. /**********************************************************
  306.  *      short zrdat32(struct Vars *v, UBYTE *buf, short length)
  307.  *
  308.  * Receive array buf of max length with ending ZDLE sequence
  309.  * and CRC-32.  Returns the ending character or error code.
  310.  **********************************************************/
  311. short zrdat32(struct Vars *v, UBYTE *buf, short length)
  312. {
  313.    short c, d;
  314.    ULONG crc32;
  315.  
  316.    crc32 = 0xFFFFFFFFL;
  317.    v->Rxcount = 0;
  318.  
  319.    for (;;)
  320.    {
  321.       if ((c = zdlread(v)) & ~0xFF)
  322.       {
  323. crcfoo:
  324.          switch (c)
  325.          {
  326.          case GOTCRCE:
  327.          case GOTCRCG:
  328.          case GOTCRCQ:
  329.          case GOTCRCW:
  330.             d = c;
  331.             c &= 0xFF;
  332.             crc32 = UPDC32(c, crc32);
  333.             if ((c = zdlread(v)) & ~0xFF)
  334.                goto crcfoo;
  335.             crc32 = UPDC32(c, crc32);
  336.             if ((c = zdlread(v)) & ~0xFF)
  337.                goto crcfoo;
  338.             crc32 = UPDC32(c, crc32);
  339.             if ((c = zdlread(v)) & ~0xFF)
  340.                goto crcfoo;
  341.             crc32 = UPDC32(c, crc32);
  342.             if ((c = zdlread(v)) & ~0xFF)
  343.                goto crcfoo;
  344.             crc32 = UPDC32(c, crc32);
  345.             if (crc32 != 0xDEBB20E3)
  346.             {
  347.                strcpy(v->Msgbuf, "Bad Data Packet CRC-32 ");
  348.                return ERROR;
  349.                }
  350.             return d;
  351.          case GOTCAN:
  352.             strcpy(v->Msgbuf, "Transfer Cancelled (Remote Sent ZCAN)");
  353.             return ZCAN;
  354.          case TIMEOUT:
  355.             strcpy(v->Msgbuf, "Data Packet Timeout ");
  356.             return c;
  357.          case RCDO:
  358.             strcpy(v->Msgbuf, "Transfer Cancelled (Remote Dropped Carrier)");
  359.             return c;
  360.          default:
  361.             strcpy(v->Msgbuf, "Unrecognizable Data Packet ");
  362.             return c;
  363.             }
  364.          }
  365.       if (--length < 0)
  366.       {
  367.          strcpy(v->Msgbuf, "Data Packet Too Long ");
  368.          return ERROR;
  369.          }
  370.       ++v->Rxcount;
  371.       *buf++ = c;
  372.       crc32 = UPDC32(c, crc32);
  373.       continue;
  374.       }
  375.    }    /* End of short zrdat32() */
  376.  
  377. /**********************************************************
  378.  *      short zgethdr(struct Vars *v)
  379.  *
  380.  * Read a ZMODEM header to hdr, either binary or hex.
  381.  *  On success return type of header.
  382.  *  Otherwise return negative on error.
  383.  **********************************************************/
  384. short zgethdr(struct Vars *v)
  385. {
  386.    short c, cancount;
  387.    long n;
  388. #ifdef DEBUGLOG
  389.    UBYTE msgbuf [128];
  390. #endif
  391.  
  392. /* n = v->Baud; */  /* Max characters before start of frame */
  393.    n = v->KSIZE * 2;/* We assume that since extra data may be generated */
  394.                     /* or lost due to line noise, that the maximum data */
  395.                     /* to the next header will be less than 8129 bytes. */
  396.                     /* Due to the fact that the Amiga's serial port can */
  397.                     /* loose data and thereby fall into the next header */
  398.                     /* this should allow another header to be found!    */
  399.    cancount = 5;
  400. again:
  401.    v->Rxframeind = v->Rxtype = 0;
  402.    switch (c = noxrd7(v))
  403.    {
  404.    case RCDO:
  405.    case TIMEOUT:
  406.       goto fifi;
  407.    case CAN:
  408.       if (--cancount <= 0)
  409.       {
  410.          c = ZCAN;
  411.          goto fifi;
  412.          }
  413.    default:
  414. agn2:
  415.       if (--n <= 0)
  416.       {
  417.          strcpy(v->Msgbuf, "Header Search Garbage Count Exceeded ");
  418.          return ERROR;
  419.          }
  420.       if (c != CAN)
  421.          cancount = 5;
  422.       goto again;
  423.    case ZPAD:              /* This is what we want. */
  424.       break;
  425.       }
  426.    cancount = 5;
  427. splat:
  428.    switch (c = noxrd7(v))
  429.    {
  430.    case ZPAD:
  431.       goto splat;
  432.    case RCDO:
  433.    case TIMEOUT:
  434.       goto fifi;
  435.    default:
  436.       goto agn2;
  437.    case ZDLE:              /* This is what we want. */
  438.       break;
  439.       }
  440.  
  441.    switch (c = noxrd7(v))
  442.    {
  443.    case RCDO:
  444.    case TIMEOUT:
  445.       goto fifi;
  446.    case ZBIN:
  447.       v->Rxframeind = ZBIN;
  448.       v->Crc32 = FALSE;
  449.       c =  zrbhdr(v);
  450.       break;
  451.    case ZBIN32:
  452.       v->Crc32 = v->Rxframeind = ZBIN32;
  453.       c =  zrbhdr32(v);
  454.       break;
  455.    case ZHEX:
  456.       v->Rxframeind = ZHEX;
  457.       v->Crc32 = FALSE;
  458.       c =  zrhhdr(v);
  459.       break;
  460.    case CAN:
  461.       if (--cancount <= 0)
  462.       {
  463.          c = ZCAN;
  464.          goto fifi;
  465.          }
  466.       goto agn2;
  467.    default:
  468.       goto agn2;
  469.       }
  470.    v->Rxpos = rclhdr(v);
  471. fifi:
  472.    switch (c)
  473.    {
  474.    case GOTCAN:
  475.       c = ZCAN;
  476.    case ZNAK:
  477.    case ZCAN:
  478.    case ERROR:
  479.    case TIMEOUT:
  480.    case RCDO:
  481.       sprintf(v->Msgbuf, "%s %s ", frametypes[c + FTOFFSET],
  482.          (c >= 0) ? "header" : "error");
  483.       }
  484.    return c;
  485.    }    /* End of short zgethdr() */
  486.  
  487. /**********************************************************
  488.  *      short zrbhdr(struct Vars *v)
  489.  *
  490.  * Receive a binary style header (type and position)
  491.  **********************************************************/
  492. short zrbhdr(struct Vars *v)
  493. {
  494.    UBYTE *hdr = v->Rxhdr;
  495.    short c, n;
  496.    USHORT crc;
  497.  
  498.    if ((c = zdlread(v)) & ~0xFF)
  499.       return c;
  500.    v->Rxtype = c;
  501.    crc = updcrc(c, 0);
  502.  
  503.    for (n = 4; --n >= 0; )
  504.    {
  505.       if ((c = zdlread(v)) & ~0xFF)
  506.          return c;
  507.       crc = updcrc(c, crc);
  508.       *hdr++ = c;
  509.       }
  510.    if ((c = zdlread(v)) & ~0xFF)
  511.       return c;
  512.    crc = updcrc(c, crc);
  513.    if ((c = zdlread(v)) & ~0xFF)
  514.       return c;
  515.    crc = updcrc(c, crc);
  516.    if (crc & 0xFFFF)
  517.    {
  518.       strcpy(v->Msgbuf, "Bad Header CRC-16 ");
  519.       return ERROR;
  520.       }
  521.    return v->Rxtype;
  522.    }    /* End of short zrbhdr() */
  523.  
  524. /**********************************************************
  525.  *      short zrbhdr32(struct Vars *v)
  526.  *
  527.  * Receive a binary style header (type and position) with
  528.  * 32 bit FCS
  529.  **********************************************************/
  530. short zrbhdr32(struct Vars *v)
  531. {
  532.    UBYTE *hdr = v->Rxhdr;
  533.    short c, n;
  534.    ULONG crc32;
  535.  
  536.    if ((c = zdlread(v)) & ~0xFF)
  537.       return c;
  538.    v->Rxtype = c;
  539.    crc32 = 0xFFFFFFFFL;
  540.    crc32 = UPDC32(c, crc32);
  541.  
  542.    for (n = 4; --n >= 0; )
  543.    {
  544.       if ((c = zdlread(v)) & ~0xFF)
  545.          return c;
  546.       crc32 = UPDC32(c, crc32);
  547.       *hdr++ = c;
  548.       }
  549.    for (n = 4; --n >= 0; )
  550.    {
  551.       if ((c = zdlread(v)) & ~0xFF)
  552.          return c;
  553.       crc32 = UPDC32(c, crc32);
  554.       }
  555.    if (crc32 != 0xDEBB20E3)
  556.    {
  557.       strcpy(v->Msgbuf, "Bad Header CRC-32 ");
  558.       return ERROR;
  559.       }
  560.    return v->Rxtype;
  561.    }    /* End of short zrbhdr32() */
  562.  
  563. /**********************************************************
  564.  *      short zrhhdr(struct Vars *v)
  565.  *
  566.  * Receive a hex style header (type and position)
  567.  **********************************************************/
  568. short zrhhdr(struct Vars *v)
  569. {
  570.    UBYTE *hdr = v->Rxhdr;
  571.    short c, n;
  572.    USHORT crc;
  573.  
  574.    if ((c = zgethex(v)) < 0)
  575.       return c;
  576.    v->Rxtype = c;
  577.    crc = updcrc(c, 0);
  578.  
  579.    for (n = 4; --n >= 0; )
  580.    {
  581.       if ((c = zgethex(v)) < 0)
  582.          return c;
  583.       crc = updcrc(c, crc);
  584.       *hdr++ = c;
  585.       }
  586.    if ((c = zgethex(v)) < 0)
  587.       return c;
  588.    crc = updcrc(c, crc);
  589.    if ((c = zgethex(v)) < 0)
  590.       return c;
  591.    crc = updcrc(c, crc);
  592.    if (crc & 0xFFFF)
  593.    {
  594.       strcpy(v->Msgbuf, "Bad Header CRC ");
  595.       return ERROR;
  596.       }
  597.    if (readock(v, 1) == '\r')
  598.       readock(v, 1);            /* Throw away possible cr/lf */
  599.    return v->Rxtype;
  600.    }    /* End of short zrhhdr() */
  601.  
  602. /**********************************************************
  603.  *      void zputhex(struct Vars *v, UBYTE c)
  604.  *
  605.  * Send a byte as two hex digits
  606.  **********************************************************/
  607. void zputhex(struct Vars *v, UBYTE c)
  608. {
  609.    static char digits[] = "0123456789abcdef";
  610.  
  611.    sendline(v, digits[(c >> 4) & 0x0F]);
  612.    sendline(v, digits[c & 0x0F]);
  613.    }    /* End of void zputhex() */
  614.  
  615. /**********************************************************
  616.  *      void zsendline(struct Vars *v, UBYTE c)
  617.  *
  618.  * Send character c with ZMODEM escape sequence encoding.
  619.  * Escape ZDLE, real DLE, XON, XOFF, and CR following @ (Telenet net escape)
  620.  **********************************************************/
  621. void zsendline(struct Vars *v, UBYTE c)
  622. {
  623.    switch (DLE_actions[c])
  624.    {
  625.    case 2:
  626.       if (v->Lastzsent != '@')
  627.          goto sendit;
  628.       /* Fallthrough */
  629.    case 1:
  630.       xsendline(v, ZDLE);
  631.       c ^= 0x40;
  632. sendit:
  633.    case 0:
  634.       xsendline(v, v->Lastzsent = c);
  635.       }
  636.    }    /* End of void zsendline() */
  637.  
  638. /**********************************************************
  639.  *      short zgethex(struct Vars *v)
  640.  *
  641.  * Decode two lower case hex digits into an 8 bit byte value
  642.  **********************************************************/
  643. short zgethex(struct Vars *v)
  644. {
  645.    short c, n;
  646.  
  647.    if ((n = noxrd7(v)) < 0)
  648.       return n;
  649.    n -= '0';
  650.    if (n > 9)
  651.       n -= ('a' - ':');
  652.    if (n & ~0xF)
  653.       return ERROR;
  654.  
  655.    if ((c = noxrd7(v)) < 0)
  656.       return c;
  657.    c -= '0';
  658.    if (c > 9)
  659.       c -= ('a' - ':');
  660.    if (c & ~0xF)
  661.       return ERROR;
  662.  
  663.    return (short) (n << 4 | c);
  664.    }    /* End of short zgethex() */
  665.  
  666. /**********************************************************
  667.  *      short zdlread(struct Vars *v)
  668.  *
  669.  * Read a byte, checking for ZMODEM escape encoding
  670.  * including CAN*5 which represents a quick abort.
  671.  **********************************************************/
  672. short zdlread(struct Vars *v)
  673. {
  674.    short c;
  675.  
  676.    if ((c = readock(v, v->Rxtimeout)) != ZDLE)
  677.       return c;
  678.    if ((c = readock(v, v->Rxtimeout)) < 0)
  679.       return c;
  680.    if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  681.       return c;
  682.    if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  683.       return c;
  684.    if (c == CAN && (c = readock(v, v->Rxtimeout)) < 0)
  685.       return c;
  686.    switch (c)
  687.    {
  688.    case CAN:
  689.       return GOTCAN;
  690.    case ZCRCE:
  691.    case ZCRCG:
  692.    case ZCRCQ:
  693.    case ZCRCW:
  694.       return (short) (c | GOTOR);
  695.    case ZRUB0:
  696.       return 0x7F;
  697.    case ZRUB1:
  698.       return 0xFF;
  699.    default:
  700.       if ((c & 0x60) ==  0x40)
  701.          return (short) (c ^ 0x40);
  702.       break;
  703.       }
  704.    strcpy(v->Msgbuf, "Bad ZedZap Escape Sequence ");
  705.    return ERROR;
  706.    }    /* End of short zdlread() */
  707.  
  708. /**********************************************************
  709.  *      short noxrd7(struct Vars *v)
  710.  *
  711.  * Read a character from the modem line with timeout.
  712.  * Eat parity, XON and XOFF characters.
  713.  **********************************************************/
  714. short noxrd7(struct Vars *v)
  715. {
  716.    short c;
  717.  
  718.    for (;;)
  719.    {
  720.       if ((c = readock(v, v->Rxtimeout)) < 0)
  721.          return c;
  722.       switch (c &= 0x7F)
  723.       {
  724.       case XON:
  725.       case XOFF:
  726.          continue;
  727.       default:
  728.          return c;
  729.          }
  730.       }
  731.    }    /* short noxrd7() */
  732.  
  733. /**********************************************************
  734.  *      void stohdr(struct Vars *v, long pos)
  735.  *
  736.  * Store long integer pos in Txhdr
  737.  **********************************************************/
  738. void stohdr(struct Vars *v, long pos)
  739. {
  740.    v->Txhdr[ZP0] = pos;
  741.    pos >>= 8;
  742.    v->Txhdr[ZP1] = pos;
  743.    pos >>= 8;
  744.    v->Txhdr[ZP2] = pos;
  745.    pos >>= 8;
  746.    v->Txhdr[ZP3] = pos;
  747.    }    /* End of void stohdr() */
  748.  
  749. /**********************************************************
  750.  *      long rclhdr(struct Vars *v)
  751.  *
  752.  * Recover a long integer from a header
  753.  **********************************************************/
  754. long rclhdr(struct Vars *v)
  755. {
  756.    long l;
  757.  
  758.    l = v->Rxhdr[ZP3];
  759.    l = (l << 8) | v->Rxhdr[ZP2];
  760.    l = (l << 8) | v->Rxhdr[ZP1];
  761.    l = (l << 8) | v->Rxhdr[ZP0];
  762.    return l;
  763.    }    /* End of long rclhdr() */
  764. /* End of Zm.c source */
  765.